package com.bestcem.xm.member.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.common.core.uitls.EnumUtil;
import com.bestcem.xm.common.core.uitls.StringUtil;
import com.bestcem.xm.member.controller.param.HttpUpdateQueryFieldParam;
import com.bestcem.xm.member.dao.ExtendFieldDao;
import com.bestcem.xm.member.dao.MemberQueryFieldDao;
import com.bestcem.xm.member.entity.mongo.QueryExtendField;
import com.bestcem.xm.member.entity.mongo.QueryField;
import com.bestcem.xm.member.entity.pojo.ExtendFieldDO;
import com.bestcem.xm.member.entity.pojo.MemberQueryFieldDO;
import com.bestcem.xm.member.enums.MemberTypeEnum;
import com.bestcem.xm.member.service.MemberQueryFieldService;
import com.bestcem.xm.member.service.dto.MemberQueryBaseFieldDTO;
import com.bestcem.xm.member.service.dto.MemberQueryExtendFieldDTO;
import com.bestcem.xm.member.service.dto.MemberQueryFieldDTO;
import com.bestcem.xm.member.service.dto.MetaFieldDTO;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.bestcem.xm.member.constant.Constants.*;

/**
 * 联系人查询字段
 *
 * @author yf.wang <yf.wang@idiaoyan.com>
 * @version V1.0
 * @date 2021/8/18
 */

@Service
public class MemberQueryFieldServiceImpl implements MemberQueryFieldService {

    @Resource
    private MemberQueryFieldDao memberQueryFieldDao;

    @Resource
    private ExtendFieldDao extendFieldDao;

    @Override
    public ServiceResult<MemberQueryFieldDTO> getQueryField(Integer memberType, String orgId) {
        // 校验联系人类型，目前只支持个人联系人、机构联系人、内部联系人
        MemberTypeEnum memberTypeEnum = EnumUtil.getEnumByIndex(MemberTypeEnum.class, memberType);
        if(MemberTypeEnum.illegalCommonMemberType(memberTypeEnum)){
            return ServiceResult.fail("联系人类型异常");
        }

        // 查询展示列信息
        MemberQueryFieldDO memberQueryField =
                memberQueryFieldDao.findOneByOrgIdAndMemberType(memberType, orgId);

        // 初始化
        if(memberQueryField == null){
            memberQueryField = new MemberQueryFieldDO();
            memberQueryField.setOrgId(orgId);
            memberQueryField.setMemberType(memberType);
        }

        MemberQueryFieldDTO dto = new MemberQueryFieldDTO();
        // 处理基础字段
        List<MemberQueryBaseFieldDTO> memberQueryBaseFieldDTOS;
        if (StrUtil.isNotEmpty(memberQueryField.getBaseFields())) {
            List<QueryField> baseFields = JSONArray.parseArray(memberQueryField.getBaseFields(), QueryField.class);
            memberQueryBaseFieldDTOS = this.buildBaseFields(memberTypeEnum, baseFields);
        }else{
            memberQueryBaseFieldDTOS = this.buildBaseFields(memberTypeEnum, new ArrayList<>());
        }
        // 构建基础字段查询列
        dto.setBaseFields(memberQueryBaseFieldDTOS);

        // 构建扩展字段查询列
        List<MemberQueryExtendFieldDTO> memberQueryExtendFieldDTOS;
        if (StrUtil.isNotEmpty(memberQueryField.getExtendFields())) {
            List<QueryExtendField> extendFields = JSONArray.parseArray(memberQueryField.getExtendFields(), QueryExtendField.class);
            memberQueryExtendFieldDTOS = this.buildExtendQueryFields(orgId, memberTypeEnum, extendFields);
        }else{
            memberQueryExtendFieldDTOS = this.buildExtendQueryFields(orgId, memberTypeEnum, new ArrayList<>());
        }
        dto.setExtendFields(memberQueryExtendFieldDTOS);
        return ServiceResult.success(dto);
    }

    /**
     * 构建基础字段展示列
     *
     * @param memberTypeEnum 联系人类型枚举
     * @return 基础字段展示列
     */
    private List<MemberQueryBaseFieldDTO> buildBaseFields(MemberTypeEnum memberTypeEnum, List<QueryField> queryFields) {
        List<MetaFieldDTO> metaFieldDTOS;
        List<String> defaultFields;
        switch (memberTypeEnum) {
            case INDIVIDUAL:
                metaFieldDTOS = INDIVIDUAL_QUERY_FIELD;
                defaultFields = INDIVIDUAL_DEFAULT_QUERY_FIELD;
                break;
            case INSTITUTION:
                metaFieldDTOS = INSTITUT_QUERY_FIELD;
                defaultFields = INSTITUTION_DEFAULT_QUERY_FIELD;
                break;
            case INTERIOR:
                metaFieldDTOS = INNER_QUERY_FIELD;
                defaultFields = INTERIOR_DEFAULT_QUERY_FIELD;
                break;
            default:
                // throw exception
                return new ArrayList<>();
        }

        List<MemberQueryBaseFieldDTO> baseFields = new LinkedList<>();
        // 默认展示列表
        if(CollectionUtils.isEmpty(queryFields)){
            for(MetaFieldDTO metaFieldDTO : metaFieldDTOS){
                MemberQueryBaseFieldDTO field = new MemberQueryBaseFieldDTO();
                field.setDisplayName(metaFieldDTO.getDisplayName());
                field.setField(metaFieldDTO.getField());
                field.setShow(defaultFields.contains(metaFieldDTO.getDisplayName()));
                baseFields.add(field);
            }
        }else{
            Map<String, QueryField> nameMap = queryFields.stream().collect(Collectors.toMap(QueryField::getDisplayName, Function.identity()));
            for(MetaFieldDTO metaFieldDTO : metaFieldDTOS){
                QueryField queryField = nameMap.get(metaFieldDTO.getDisplayName());
                MemberQueryBaseFieldDTO field = new MemberQueryBaseFieldDTO();
                field.setDisplayName(metaFieldDTO.getDisplayName());
                field.setField(metaFieldDTO.getField());
                field.setShow(queryField != null && queryField.getShow());
                baseFields.add(field);
            }
        }
        return baseFields;
    }

    private List<MemberQueryExtendFieldDTO> buildExtendQueryFields(String orgId, MemberTypeEnum memberTypeEnum, List<QueryExtendField> queryExtendFields) {
        // 扩展字段默认不展示
        if(queryExtendFields == null){
            queryExtendFields = new ArrayList<>();
        }

        Map<org.bson.types.ObjectId, QueryExtendField> fieldIdMap = new HashMap<>(queryExtendFields.size());
        for(QueryExtendField queryExtendField : queryExtendFields){
            org.bson.types.ObjectId extendFieldId = new org.bson.types.ObjectId(queryExtendField.getId());
            fieldIdMap.put(extendFieldId, queryExtendField);
        }

        List<ExtendFieldDO> extendFields = extendFieldDao.listMemberExtendField(orgId, memberTypeEnum.getIndex());
        if(CollectionUtils.isEmpty(extendFields)){
            return new ArrayList<>();
        }

        List<MemberQueryExtendFieldDTO> result = new ArrayList<>(extendFields.size());
        for(ExtendFieldDO extendField : extendFields){
            MemberQueryExtendFieldDTO queryField = new MemberQueryExtendFieldDTO();
            queryField.setType(extendField.getType());
            queryField.setName(extendField.getName());
            queryField.setId(extendField.getFieldId());
            QueryExtendField queryExtendField = fieldIdMap.get(new org.bson.types.ObjectId(extendField.getFieldId()));
            queryField.setShow(queryExtendField != null && queryExtendField.getShow());
            result.add(queryField);
        }
        return result;
    }


    /**
     * 添加默认的查询字段
     *
     * @param attribute
     * @param orgId
     * @return
     */
    private MemberQueryFieldDTO buildDefaultFields(Integer attribute, String orgId) {
        // 获取扩展字段
        List<ExtendFieldDO> extendFields = extendFieldDao.listMemberExtendField(orgId, attribute);
        MemberQueryFieldDTO dto = new MemberQueryFieldDTO();
        List<MemberQueryBaseFieldDTO> baseFields = null;
        switch (EnumUtil.getEnumByIndex(MemberTypeEnum.class, attribute)) {
            case INDIVIDUAL:
                baseFields = INDIVIDUAL_QUERY_FIELD.stream().map(info -> {
                    MemberQueryBaseFieldDTO field = new MemberQueryBaseFieldDTO();
                    field.setDisplayName(info.getDisplayName());
                    field.setField(info.getField());
                    if (INDIVIDUAL_DEFAULT_QUERY_FIELD.contains(info.getDisplayName())) {
                        field.setShow(true);
                    } else {
                        field.setShow(false);
                    }
                    return field;
                }).collect(Collectors.toList());
                break;
            case INSTITUTION:
                baseFields = INSTITUT_QUERY_FIELD.stream().map(info -> {
                    MemberQueryBaseFieldDTO field = new MemberQueryBaseFieldDTO();
                    field.setDisplayName(info.getDisplayName());
                    field.setField(info.getField());
                    if (INSTITUTION_DEFAULT_QUERY_FIELD.contains(info.getDisplayName())) {
                        field.setShow(true);
                    } else {
                        field.setShow(false);
                    }
                    return field;
                }).collect(Collectors.toList());
                break;
            case INTERIOR:
                baseFields = INNER_QUERY_FIELD.stream().map(info -> {
                    MemberQueryBaseFieldDTO field = new MemberQueryBaseFieldDTO();
                    field.setDisplayName(info.getDisplayName());
                    field.setField(info.getField());
                    if (INTERIOR_DEFAULT_QUERY_FIELD.contains(info.getDisplayName())) {
                        field.setShow(true);
                    } else {
                        field.setShow(false);
                    }
                    return field;
                }).collect(Collectors.toList());
                break;
        }
        dto.setBaseFields(baseFields);
        List<MemberQueryExtendFieldDTO> extendQueryFields = buildExtendQueryField(extendFields);
        dto.setExtendFields(extendQueryFields);
        return dto;
    }

    private List<MemberQueryExtendFieldDTO> buildExtendQueryField(List<ExtendFieldDO> extendFields) {
        if (CollUtil.isNotEmpty(extendFields)) {
            List<MemberQueryExtendFieldDTO> queryFields = extendFields.stream().map(field -> {
                MemberQueryExtendFieldDTO queryField = new MemberQueryExtendFieldDTO();
                queryField.setType(field.getType());
                queryField.setName(field.getName());
                queryField.setId(field.getFieldId());
                queryField.setShow(false);
                return queryField;
            }).collect(Collectors.toList());
            return queryFields;
        }
        return new ArrayList<>();
    }

    @Override
    public ServiceResult<String> updateQueryField(HttpUpdateQueryFieldParam param) {
        MemberQueryFieldDO memberQueryField =
                memberQueryFieldDao.findOneByOrgIdAndMemberType(param.getAttribute(), param.getOrgId());

        if (ObjectUtil.isEmpty(memberQueryField)) {
            // 添加
            memberQueryField = buildMemberQueryFieldDo(param);
            memberQueryField.setCreateTime(DateUtil.getCommonDate());
            memberQueryField.setUpdateTime(memberQueryField.getCreateTime());
            memberQueryFieldDao.createMemberQueryField(memberQueryField);
        } else {
            // 更新
            memberQueryField.setBaseFields(JSONObject.toJSONString(param.getBaseFields()));
            memberQueryField.setExtendFields(JSONObject.toJSONString(param.getExtendFields()));
            memberQueryField.setUpdateTime(DateUtil.getCommonDate());
            memberQueryFieldDao.updateMemberQueryField(memberQueryField);
        }
        return ServiceResult.success();
    }

    /**
     * 构建 MemberQueryFieldDo
     *
     * @param param
     * @return
     */
    private MemberQueryFieldDO buildMemberQueryFieldDo(HttpUpdateQueryFieldParam param) {
        MemberQueryFieldDO memberQueryField = new MemberQueryFieldDO();
        // 联系人类型
        memberQueryField.setMemberType(param.getAttribute());
        // 组织id
        memberQueryField.setOrgId(param.getOrgId());
        // id
        memberQueryField.setId(StringUtil.getId());
        memberQueryField.setBaseFields(JSONObject.toJSONString(param.getBaseFields()));
        memberQueryField.setExtendFields(JSONObject.toJSONString(param.getExtendFields()));
        return memberQueryField;
    }

    @Override
    public List<MemberQueryFieldDO> findAll(int offset, int batchSize) {
        return memberQueryFieldDao.findAll(offset, batchSize);
    }

    @Override
    public void updateBaseQueryField(String id, String baseFields) {
        memberQueryFieldDao.updateBaseQueryField(id, baseFields);
    }
}
